---
id: dbcontext-entitytrigger
title: 9.25. 实体数据监听器
sidebar_label: 9.25. 实体数据监听器
---

## 9.25.1 实体数据监听器

在最新的 `Furion` 的 `1.1.6+` 版本中，新增了 `IEntityChangedListener` 实体数据监听接口，可以监听 `EFCore` 任何实体表 `增删改` 操作。

## 9.25.2 有何作用

- 类似数据库 `触发器` 功能，可实现 `增删改` 监听
- 可以实现特殊操作，比如刷新缓存，记录日志等

## 9.25.3 如何使用

在 `Furion` 框架中，默认不启用实体数据监听器，如想启用，只需要在 `数据库上下文` 构造函数中启用即可：

### 9.25.3.1 启用数据监听

```cs {11}
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;

namespace Furion.EntityFramework.Core
{
    [AppDbContext("Sqlite3ConnectionString")]
    public class DefaultDbContext : AppDbContext<DefaultDbContext>
    {
        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
        {
            EnabledEntityChangedListener = true;
        }
    }
}
```

### 9.25.3.2 监听特定实体数据

```cs {9,30-41}
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;

namespace Furion.Core
{
    public class Post : Entity, IEntityChangedListener<Post>
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public Post()
        {
            CreatedTime = DateTimeOffset.UtcNow;
            IsDeleted = false;
        }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Person 集合
        /// </summary>
        public ICollection<Person> Persons { get; set; }

        /// <summary>
        /// 实体更改后触发
        /// </summary>
        /// <param name="entity">新数据</param>
        /// <param name="oldEntity">旧数据</param>
        /// <param name="dbContext">数据库上下文</param>
        /// <param name="dbContextLocator">数据库上下文定位器</param>
        /// <param name="state">实体状态</param>
        public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)
        {
            // 刷新缓存
            App.GetService<IMemoryCache>().Set("Key", "Value");
        }
    }
}
```

## 9.25.4 `IEntityChangedListener` 定义

```cs {25}
/// <summary>
/// 实体数据改变监听依赖接口
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public interface IEntityChangedListener<TEntity>
    where TEntity : class, IPrivateEntity, new()
{
    /// <summary>
    /// 监听数据改变之前（仅支持EFCore操作）
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="dbContext"></param>
    /// <param name="dbContextLocator"></param>
    /// <param name="state"></param>
    void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }

    /// <summary>
    /// 监听数据改变之后（仅支持EFCore操作）
    /// </summary>
    /// <param name="newEntity">新值</param>
    /// <param name="oldEntity">旧值</param>
    /// <param name="dbContext"></param>
    /// <param name="dbContextLocator"></param>
    /// <param name="state"></param>
    void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);

    /// <summary>
    /// 监听数据改变失败（仅支持EFCore操作）
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="dbContext"></param>
    /// <param name="dbContextLocator"></param>
    /// <param name="state"></param>
    void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }
}
```

## 9.29.5 `[NotChangedListener]` 跳过监听

默认情况下，`Furion` 框架会对所有新增、更新、编辑的实体进行监听，有些时候我们无需监听特定实体，只需要在实体上贴 `[NotChangedListener]` 特性即可。

## 9.29.6 反馈与建议

:::note 与我们交流

给 Furion 提 [Issue](https://gitee.com/dotnetchina/Furion/issues/new?issue)。

:::
